package com.mybatis.utils;

import com.intellij.database.model.*;
import com.intellij.database.psi.DbDataSource;
import com.intellij.database.psi.DbTable;
import com.intellij.database.util.DasUtil;
import com.intellij.util.containers.JBIterable;
import com.mybatis.enums.DataBaseType;
import org.mybatis.generator.api.IntellijColumnInfo;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class DataTableUtils {
    /**
     * 获取dataSource 下面所有的表,除系统表之外
     *
     * @param dbDataSource dbDataSource
     * @return List<DasTable>
     */
    public static List<DasTable> getTables(DbDataSource dbDataSource) {
        List<? extends DasTable> collection = DasUtil.getTables(dbDataSource).toList();
        if (collection.isEmpty()) {
            return new ArrayList<>();
        }
        return collection.stream().filter(dasTable -> !dasTable.isSystem()).collect(Collectors.toList());
    }

    public static List<IntellijColumnInfo> getColumns(DasTable dasTable, DbTable dbTable) {
        JBIterable<? extends DasColumn> columns = DasUtil.getColumns(dasTable);
        List<IntellijColumnInfo> columnInfos = new ArrayList<>();
        DataBaseType dataBaseType = getDataBaseType(dbTable);
        for (DasColumn column : columns) {
            IntellijColumnInfo columnInfo = new IntellijColumnInfo();
            columnInfo.setAutoIncrement(DasUtil.isAutoGenerated(column));
            columnInfo.setGeneratedColumn(DasUtil.isAutoGenerated(column));
            columnInfo.setSize(column.getDataType().getLength());
            columnInfo.setName(column.getName());
            columnInfo.setDataType(JdbcUtils.convertTypeNameToJdbcType(column.getDataType().typeName, column.getDataType().size, dataBaseType.name()));
            columnInfo.setTypeName(JdbcUtils.convertJdbcTypeInformation(columnInfo.getDataType(), column.getDataType().size, false).getJdbcTypeName());
            //小数位
            columnInfo.setDecimalDigits(column.getDataType().getScale());
            columnInfo.setRemarks(column.getComment());
            columnInfo.setColumnDefaultValue(column.getDefault());
            //是否可以为空
            columnInfo.setNullable(!column.isNotNull());
            columnInfo.setKeySeq(column.getPosition());
            columnInfos.add(columnInfo);
        }
        return columnInfos;
    }

    public static List<IntellijColumnInfo> getPriMaryKey(DasTable dasTable, DbTable dbTable) {
        DasTableKey dasTableKey = DasUtil.getPrimaryKey(dasTable);
        if (dasTableKey == null) {
            return null;
        }
        MultiRef<? extends DasTypedObject> columnsRef = dasTableKey.getColumnsRef();
        MultiRef.It<? extends DasTypedObject> iterate = columnsRef.iterate();
        List<IntellijColumnInfo> columnInfos = getColumns(dasTable, dbTable);
        List<IntellijColumnInfo> resultList = new ArrayList<>();
        short s = 0;
        while (iterate.hasNext()) {
            String columnName = iterate.next();
            IntellijColumnInfo columnInfo = columnInfos.stream().filter(info -> info.getName().equals(columnName)).findFirst().orElse(null);
            if (columnInfo != null) {
                columnInfo.setKeySeq(s);
                resultList.add(columnInfo);
                s = (short) (s + 1);
            }
        }
        return resultList;
    }

    public static DataBaseType getDataBaseType(DbTable dbTable) {
        RawConnectionConfig rawConnectionConfig = dbTable.getDataSource().getConnectionConfig();
        if (rawConnectionConfig == null) {
            return DataBaseType.UNKNOWN;
        }
        String url = rawConnectionConfig.getUrl();
        if (url.contains("mysql")) {
            return DataBaseType.MySql;
        } else if (url.contains(":oracle"))
            return DataBaseType.Oracle;
        else if (url.contains(":postgresql"))
            return DataBaseType.PostgreSQL;
        else if (url.contains(":sqlserver"))
            return DataBaseType.SqlServer;
        else if (url.contains(":sqlite")) {
            return DataBaseType.Sqlite;
        }
        return DataBaseType.UNKNOWN;
    }


}
